package annotation;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 自定义注解,名字为Entity
 * 注意：我们自己写的所有注解都默认继承Annotation接口
 * @Target用于定义，你字节写注解可以描述哪些对象
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Entity {
    String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface ID{
   int value();
}
@Target(ElementType.PARAMETER)
@interface Validate{}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@interface Log{}

/**
 * 使用注解描述类
 */
@Log
@Entity("tb_user")
class User{
   @ID(100)
   private Integer id;

   public void setId(@Validate Integer id){
       this.id=id;
   }
   @Log
   public Integer getId() {
      return id;
   }
}

public class AnnotationDemo01 {
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
      //案例1：获取User类上的Entity注解，然后获取注解中的value属性值
      //1.获取类的字节码对象
      Class<User> userClass = User.class;
      //2.判定类上是否有指定注解
      boolean flag = userClass.isAnnotationPresent(Entity.class);
      System.out.println(flag);
      //3.获取类上的注解
      Entity entity = userClass.getAnnotation(Entity.class);
      System.out.println(entity instanceof Annotation);//true
      System.out.println(entity.value());

      //案例2：将@ID注解中的值100,赋值给@ID注解描述的id属性
      //1.获取User类中的ID属性
      Field fis=userClass.getDeclaredField("id");
      //2.获取属性上的ID注解
      boolean hasId = fis.isAnnotationPresent(ID.class);
      if(!flag)return;
      ID id = fis.getAnnotation(ID.class);
      //3.调用注解对象的value方法获取注解中的值
      int idValue=id.value();
      //4.为ID注解描述的属性赋值
      fis.setAccessible(true);
      User user=new User();
      fis.set(user,idValue);//为user对象的id属性赋值
      System.out.println(fis.get(user));

      //案例3：获取类中的所有方法，假如方法上有@Log注解，则输出一句话，这个方法执行要记录日志
      Method[] methods = userClass.getDeclaredMethods();
      for (Method method : methods) {
          boolean hasLog = method.isAnnotationPresent(Log.class);
          if(hasLog){
              System.out.println("执行"+method.getName()+"方法要记录日志");
          }
      }
   }
}
